#!/usr/bin/env python

#
# GLPres - 0.1
#
# The OpenGL Presentation Framework
#
# Written by: Fabio Rotondo
# OpenGL Code by: Alessandro Molina
#
# This software is Free Software under GPLv2 License
#

import pygame, os
from pygame.locals import *
from OpenGL.GL import *
from OpenGL.GLU import *

from fxsurface import FXSurface

class GLObj ( object ):
	def __init__(self, x = 0, y = 0, opacity = 1.0, scale = 1.0, rotation = None ):
		self.x = x
		self.y = y

		self.opacity = opacity
		self.visible = 1
		self.rotation = rotation
		self.scale = scale

		self.name = ""
		self.kind = ""

	def _make_textured_rect(self):
		self._call_list = glGenLists(1)
		glNewList(self._call_list, GL_COMPILE);
		glBindTexture(GL_TEXTURE_2D, self._texture)
		glBegin(GL_QUADS)
		glTexCoord2f(0, 0); glVertex2f(0, 0)
		glTexCoord2f(0, 1); glVertex2f(0, self.h)
		glTexCoord2f(1, 1); glVertex2f(self.w,  self.h)
		glTexCoord2f(1, 0); glVertex2f(self.w, 0)
		glEnd()
		glEndList()

	def _make_text ( self, image ):
		height = image.get_height()
		width = image.get_width()

		h = 16
		while(h < height):
			h = h*2

		# h = ( ( height / 64 ) + 1 ) * 64

		w = 16
		while(w < width):
			w = w*2

		#print "width: %d - w: %d" % ( width, w )
		#print "heiht: %d - w: %d" % ( height, h )

		self._texture= glGenTextures(1) 
		glBindTexture(GL_TEXTURE_2D, self._texture)
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR )
		glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR )
		
		emptyList = "\x00" * w*h*4
		glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, emptyList )
		
		textureData = pygame.image.tostring(image, "RGBA", 1)
		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, image.get_width(), image.get_height(), GL_RGBA, GL_UNSIGNED_BYTE, textureData)

		self.w = w
		self.h = h		

	def draw(self):
		if not self.visible: return

		glPushMatrix()
		glTranslatef(self.x, self.y, 0)
		glColor4f(1, 1, 1, self.opacity)

		if self.rotation is not None:
			print "GL ROT: ", self.rotation
			#glTranslatef ( -self.w, -self.h, 0 )
			glRotatef ( self.rotation, 0.0, 0.0, 1.0 )

		glScale ( self.scale, self.scale, 1.0 )
		glCallList(self._call_list)
		glPopMatrix()

	def set_opacity ( self, v ):
		if v < 0.0: v = 0.0
		elif v > 1.0 : v = 1.0

		self.opacity = v

	def add_rotation ( self, rot ):
		if self.rotation is None:
			self.rotation = 0.0

		rot = self.rotation + rot

		if rot >= 360.0:
			rot -= 360.0

		self.rotation = rot
		if self.rotation == 0.0:
			self.rotation = None

class GLImage ( GLObj ):
	def __init__(self, x, y, fname, opacity=1.0, scale = 1.0, rotation = None ):
		super ( GLImage, self ).__init__ ( x, y, opacity, scale = scale, rotation = rotation )

		self.kind = "image"
		self._load_img ( fname )
		self._make_textured_rect()

	def _load_img ( self, fname ):
		image = pygame.image.load ( fname ).convert_alpha ()
		self._make_text ( image )


class GLText ( GLObj ):
	def __init__(self, x, y, text, font=None, font_size=12, color=(255,255,255), opacity=1.0, effects = None, scale = 1.0, rotation = None ):
		super ( GLText, self ).__init__ ( x, y, opacity, scale = scale, rotation = rotation )

		self.text = text
		self.kind = "text"

		#self._make_txt ( text, font, font_size, color )

		self.fxsurf = FXSurface ()

		self.fxsurf.text ( text, font_name = font, font_size = font_size, color = color, antialias = 1, effects = effects )

		if effects: self._apply_fx ( effects )

		self._make_text ( self.fxsurf.get () )
		self._make_textured_rect()

	def _apply_fx ( self, effects ):
		if "blur" in effects:
			self.fxsurf.blur ( ** effects [ 'blur' ] )

	"""
	def _make_txt ( self, text, font, font_size, color  ):
		fontObj = pygame.font.Font ( font, font_size )
		image = fontObj.render ( text, 1, color )

		self._make_text ( image )
	"""

class GLWorld(object):
	def __init__(self, width, height, fullscreen ):
		self.objects = []

		self._initScreen ( width, height, fullscreen  )

	def _initScreen ( self, w, h, fullscreen ):
		fs = 0
		if fullscreen: fs = pygame.FULLSCREEN

		pygame.display.set_mode ( ( w, h ), pygame.OPENGL | pygame.DOUBLEBUF | fs )

		glClearColor ( 0.0, 0.0, 0.0, 1.0 )
		glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )

		glMatrixMode ( GL_PROJECTION )
		glLoadIdentity ()
		gluOrtho2D ( 0, w, 0, h )
		glMatrixMode ( GL_MODELVIEW )

		glEnable ( GL_TEXTURE_2D )
		glEnable ( GL_BLEND )
		glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA )

	def add ( self, obj ):
		self.objects.append ( obj )

	def draw ( self ):
		self.clear_display ()

		for o in self.objects:
			if o.visible: o.draw ()

		self.flip ()


	def clear_display ( self ):
		glClear ( GL_COLOR_BUFFER_BIT )
		glLoadIdentity ()

	def flip ( self ):
		pygame.display.flip ()

	def clear ( self ):
		self.objects = []
		

def main():
	pygame.init()
	clock = pygame.time.Clock ()

	world = GLWorld ( 800, 600 )

	hello = GLText ( 300, 300, 'Hello', font_size=48, color = ( 0, 0, 255 ) )
	txt_world = GLText ( 370, 300, 'World', font_size=128 )
	bg = GLImage ( 0, 0, 'data/bg01.jpg' )
	circle = GLImage ( 0, 0, 'data/circle.png' )

	world.add( bg )
	world.add( hello )
	world.add( txt_world )
	world.add( circle )
	world.add(GLText(250, 300, 'Ciao', font_size=48, color=(255, 0, 0), opacity=0.3))

	done = False
	bg.opacity = 0
	while not done:
		world.draw()

		hello.y -= 0.5
		txt_world.opacity -= 0.01
		bg.opacity += 0.03
		circle.y -= 1

		eventlist = pygame.event.get()

		for event in eventlist:
			if event.type == QUIT \
			   or event.type == KEYDOWN and event.key == K_ESCAPE:
				done = True

		clock.tick ( 50 )

if __name__ == '__main__':
	os.chdir ( ".." )
	main()

